package com.linkstec.mot.dao;

import java.sql.Connection;
import java.sql.PreparedStatement;
import java.sql.SQLException;
import java.sql.Timestamp;
import java.util.Date;
import java.util.List;

import javax.annotation.PostConstruct;

import org.apache.ibatis.session.ExecutorType;
import org.apache.ibatis.session.SqlSession;
import org.apache.ibatis.session.SqlSessionFactory;
import org.mybatis.spring.support.SqlSessionDaoSupport;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Repository;

import com.linkstec.mot.cons.Constants;
import com.linkstec.mot.util.ConfigUtil;
import com.linkstec.mot.util.ExceptionTracker;

/**
 * @author PENGYAO
 * 
 */
@Repository("batchDao")
public class BatchDao extends SqlSessionDaoSupport {

	/**
	 * 打印提交数据库发生异常错误数据logger。
	 */
	private static Logger logger = LoggerFactory
			.getLogger("database.error.log");

	// @Resource(name = "sqlSessionFactory")
	@Autowired
	private SqlSessionFactory sqlSessionFactory;

	@PostConstruct
	public void SqlSessionFactory() {
		super.setSqlSessionFactory(sqlSessionFactory);
	}

	/**
	 * 
	 * @param sql
	 * @param list
	 * @return
	 * @throws SQLException
	 */
	public int batchUpdate(String sql, List<Object[]> list) throws Exception {
		SqlSession batchSession = sqlSessionFactory.openSession(
				ExecutorType.BATCH, false);

		Connection conn = null;
		PreparedStatement pstmt = null;
		int loopCount = 0;
		int resultCount = 0;
		int m = 0;
		try {
			conn = batchSession.getConnection();
			conn.setAutoCommit(false);
			pstmt = conn.prepareStatement(sql);

			for (int i = 0; i < list.size(); i++) {
				loopCount++;
				resultCount++;
				Object[] objItem = list.get(i);
				for (int j = 0; j < objItem.length; j++) {
					if (objItem[j] instanceof Date) {
						pstmt.setObject(j + 1, new Timestamp(
								((Date) objItem[j]).getTime()));
					} else {
						pstmt.setObject(j + 1, objItem[j]);
					}
				}
				pstmt.addBatch();
//				if (loopCount == Constants.BATCH_DEAL_NUM) {// Constants.BATCH_DEAL_NUM
				if (loopCount == Integer.parseInt(ConfigUtil.getProperty("batchDealNum"))) {// Constants.BATCH_DEAL_NUM
					pstmt.executeBatch();
					pstmt.clearBatch();
					conn.commit();
					loopCount = 0;
					m = i;
				}
			}
			if (loopCount > 0) {
				pstmt.executeBatch();
				pstmt.clearBatch();
				conn.commit();
				loopCount = 0;
			}
		} catch (Exception e) {
			if (m != 0) {
				m = m + 1;
			}
			while (true) {
				StringBuilder errStr = new StringBuilder();
				errStr.append("sql = ");
				errStr.append(sql);
				errStr.append("\nparams = ");
				Object[] errItem = list.get(m);
				for (int i = 0; i < errItem.length; i++) {
					Object item = errItem[i];
					if (null != item) {
						errStr.append(item.toString());
					} else {
						errStr.append("null");
					}
					if (i != errItem.length - 1) {
						errStr.append(",");
					}
				}
				logger.error(errStr.toString());
				m++;
				if (m == list.size()) {
					break;
				}
			}
			throw e;
		} finally {
			if (null != pstmt) {
				pstmt.close();
			}
			batchSession.close();
		}
		return resultCount;
	}
	/**
	 * 
	 * @param list
	 * @return
	 * @throws SQLException
	 */
	@SuppressWarnings("resource")
	public int batchUpdateAll(List<String> list) throws Exception {
		SqlSession batchSession = sqlSessionFactory.openSession(
				ExecutorType.BATCH, false);
		Connection conn = null;
		PreparedStatement pstmt = null;
		int loopCount = 0;
		int resultCount = 0;
		int m = 0;
		StringBuilder sqlStr = new StringBuilder("insert /*+append, parallel*/ all ");
		try {
			conn = batchSession.getConnection();
			conn.setAutoCommit(false);
			
			int size = list.size();
			for (int i = 0; i < size; i++) {
				loopCount++;
				resultCount++;
				sqlStr.append(list.get(i) + " ");
				if (loopCount == Integer.parseInt(ConfigUtil.getProperty("batchDealNum"))) {// Constants.BATCH_DEAL_NUM
					sqlStr.append(" select 1 from dual");
					pstmt = conn.prepareStatement(sqlStr.toString());
					pstmt.execute();
					conn.commit();
					sqlStr.delete(0, sqlStr.length());
					sqlStr.append("insert /*+append, parallel*/ all ");
					loopCount = 0;
					m = i;
				}
			}
			if (loopCount > 0) {
				sqlStr.append(" select 1 from dual");
				pstmt = conn.prepareStatement(sqlStr.toString());
				pstmt.execute();
				conn.commit();
				sqlStr.delete(0, sqlStr.length());
				sqlStr.append("insert /*+append, parallel*/ all ");
				loopCount = 0;
			}
		} catch (Exception e) {
			if (m != 0) {
				m = m + 1;
			}
			logger.error("出错了" + ExceptionTracker.trace(e));
			while (true) {
				StringBuilder errStr = new StringBuilder();
				errStr.append("sql = ");
				errStr.append(sqlStr);
				errStr.append("\nparams = ");
				logger.error(errStr.toString());
				m++;
				if (m >= list.size()) {
					break;
				}
			}
			throw e;
		} finally {
			if (null != pstmt) {
				pstmt.close();
			}
			batchSession.close();
		}
		return resultCount;
	}
}